using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using Cysharp.Threading.Tasks;
using Unity.Collections;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

namespace DataCenterSystem.Samples
{
    /// <summary>
    /// 数据中心系统示例
    /// </summary>
    public partial class DataCenterSystemSample : MonoBehaviour
    {
        /// <summary>
        /// 数据服务实体
        /// </summary>
        protected DataService_Entity DataService;

        #region C#类型

        /// <summary>
        /// 测试类
        /// </summary>
        protected class TestClass
        {
            /*
             * Primitive Types
             */
            public int intType = 1;
            public float floatType = 1;
            public string stringType = "1";
            public byte byteType = 1;
            public bool boolType = true;
            public char charType = '1';
            public short shortType = 1;
            public double doubleType = 1;
            public long longType = 1;
            public uint uintType = 1;
            public ushort ushortType = 1;
            public ulong ulongType = 1;
            public enum EnumDemo
            {
                test1 = 0,
                test2
            }
            public EnumDemo enumType = EnumDemo.test2;
            public DateTime dateTimeType = DateTime.Now;
            public Guid guidType = Guid.NewGuid();
            
            /*
             * Collections
             */
            public int[] intArray = new int[] { 1, 2, 3 };
            public int[][] intArray2 = new int[][] { new int[] { 1, 2, 3 }, new int[] { 4, 5, 6 } };
            public int[][][] intArray3 = new int[][][] { new int[][] { new int[] { 1, 2, 3 }, new int[] { 4, 5, 6 } }, new int[][] { new int[] { 7, 8, 9 }, new int[] { 10, 11, 12 } } };
            public Dictionary<int,string> dict = new Dictionary<int, string>() { { 1, "1" }, { 2, "2" } };
            public ConcurrentDictionary<int,string> concurrentDict = new ConcurrentDictionary<int, string>();
            public List<int> list = new List<int>() { 1, 2, 3 };
            public Queue<int> queue = new Queue<int>();
            public HashSet<int> hashSet = new HashSet<int>();
            public Stack<int> stack = new Stack<int>();
            public Tuple<int> tuple = new Tuple<int>(1);
            public ArrayList arrayList = new ArrayList(){1,2,3};
            public NativeArray<int> nativeArray = new NativeArray<int>(new int[] { 1, 2, 3 }, Allocator.Persistent);

            public GameObject gb;
            public Text tx;
            public Vector2 vc2;
            public Vector3 vc3;
            
            public TestClass()
            {
                concurrentDict.TryAdd(1, "1");
                queue.Enqueue(1);
                hashSet.Add(1);
                stack.Push(1);
            }
        }

        protected TestClass testClass = new TestClass();
        #endregion

        #region Unity3d类型 很多其他类型未列出，看同级目录下的支持类型文档

        public GameObject testGameObject;
        public Text text;
        public Vector2 vector2 = Vector2.left;
        public Vector3 vector3 = Vector3.left;

        #endregion

        /*
         * 缓存key 每一个key都独立唯一 例如：不能file存了，在prefs再用
         */
        protected string fileKey = "testClass_File";
        protected string prefsKey = "testClass_Prefs";
        protected string memoryKey = "testClass_Memory";

        /// <summary>
        /// 异步存储 并发测试
        /// </summary>
        protected bool asyncLoadSaveConcurrentTest = false;
        public Text asyncLoadSaveConcurrentTestText = null;
    }

    public partial class DataCenterSystemSample
    {
        /// <summary>
        /// 初始化数据服务实体
        /// </summary>
        public void Init_Entity()
        {
            DataService = new DataService_Entity();
            
            testClass.gb = testGameObject;
            testClass.tx = text;
            testClass.vc2 = vector2;
            testClass.vc3 = vector3;
            
            Debug.Log($"Init_Entity 数据服务 初始化完成");
        }

        #region 测试并发读取

        /// <summary>
        /// 切换异步存储压测状态
        /// </summary>
        public void Change_asyncLoadSaveConcurrentTest()
        {
            asyncLoadSaveConcurrentTest = !asyncLoadSaveConcurrentTest;
        }

        /// <summary>
        /// 更新
        /// </summary>
        private void Update()
        {
            asyncLoadSaveConcurrentTestText.text = $"异步存储压测开启状态: {asyncLoadSaveConcurrentTest.ToString()}";
            if(DataService == null || !DataService.IsInited() || !asyncLoadSaveConcurrentTest) return;
            
            UniTask.ToCoroutine(async () =>
            {
                Test_Save_File();
            });
            UniTask.ToCoroutine(async () =>
            {
                Test_Load_File();
            });
            UniTask.ToCoroutine(async () =>
            {
                Test_Save_Prefs();
            });
            UniTask.ToCoroutine(async () =>
            {
                Test_Load_Prefs();
            });
            UniTask.ToCoroutine(async () =>
            {
                Test_Save_Memory();
            });
            UniTask.ToCoroutine(async () =>
            {
                Test_Load_Memory();
            });
        }

        /// <summary>
        /// 固定更新
        /// </summary>
        private void FixedUpdate()
        {
            if(DataService == null || !DataService.IsInited() || !asyncLoadSaveConcurrentTest) return;
            UniTask.ToCoroutine(async () =>
            {
                Test_Save_File();
            });
            UniTask.ToCoroutine(async () =>
            {
                Test_Load_File();
            });
            UniTask.ToCoroutine(async () =>
            {
                Test_Save_Prefs();
            });
            UniTask.ToCoroutine(async () =>
            {
                Test_Load_Prefs();
            });
            UniTask.ToCoroutine(async () =>
            {
                Test_Save_Memory();
            });
            UniTask.ToCoroutine(async () =>
            {
                Test_Load_Memory();
            });
        }

        #endregion

        #region Setting

        /// <summary>
        /// 设置存储路径
        /// </summary>
        public void Test_Setting_SavePath()
        {
            UniTask.ToCoroutine(async () =>
            {
                await DataService.Setting_SavePath_All(DataService_Entity.Directory.CustomPath, "这里填写对应三方平台的存储路径");
                Debug.Log("Test_Setting_SavePath 设置自定义存储路径成功");
            });
        }

        #endregion
        
        #region File

        /// <summary>
        /// 测试存储文件
        /// </summary>
        public void Test_Save_File()
        {
            UniTask.ToCoroutine(async () =>
            {
                await DataService.SaveOrUpdate_File(fileKey, testClass);
                Debug.Log("Test_Save_File 存储数据成功");
            });
        }

        /// <summary>
        /// 测试加载文件
        /// </summary>
        public void Test_Load_File()
        {
            UniTask.ToCoroutine(async () =>
            {
                TestClass tc = await DataService.LoadData_File<TestClass>(fileKey);
                if (tc != null)
                {
                    Debug.Log("Test_Load_File 读取数据成功");
                }
            });
        }

        /// <summary>
        /// 测试文件是否存在
        /// </summary>
        public void Test_ContainsKey_File()
        {
            UniTask.ToCoroutine(async () =>
            {
                bool isIn = await DataService.ContainsKey_File(fileKey);
                Debug.Log($"Test_ContainsKey_File isIn: {isIn}");
            });
        }

        /// <summary>
        /// 测试删除文件
        /// </summary>
        public void Test_DeletData_File()
        {
            UniTask.ToCoroutine(async () =>
            {
                bool isDele = await DataService.DeletData_File(fileKey);
                Debug.Log($"Test_DeletData_File isIn: {isDele}");
            });
        }

        /// <summary>
        /// 测试清除文件
        /// </summary>
        public void Test_ClearSave_File()
        {
            UniTask.ToCoroutine(async () =>
            {
                bool isIn = await DataService.ContainsKey_File(fileKey);
                Debug.Log($"Test_ClearSave_File isIn: {isIn}");

                await DataService.ClearSave_File();
                
                bool isInEnd = await DataService.ContainsKey_File(fileKey);
                Debug.Log($"Test_ClearSave_File isInEnd: {isInEnd}");
            });
        }
        
        #endregion

        #region Prefs

        /// <summary>
        /// 测试存储Prefs
        /// </summary>
        public void Test_Save_Prefs()
        {
            UniTask.ToCoroutine(async () =>
            {
                await DataService.SaveOrUpdate_Prefs(prefsKey, testClass);
                Debug.Log("Test_Save_Prefs 存储数据成功");
            });
        }

        /// <summary>
        /// 测试加载Prefs
        /// </summary>
        public void Test_Load_Prefs()
        {
            UniTask.ToCoroutine(async () =>
            {
                TestClass tc = await DataService.LoadData_Prefs<TestClass>(prefsKey);
                if (tc != null)
                {
                    Debug.Log("Test_Load_Prefs 读取数据成功");
                }
            });
        }

        /// <summary>
        /// 测试Prefs是否存在
        /// </summary>
        public void Test_ContainsKey_Prefs()
        {
            UniTask.ToCoroutine(async () =>
            {
                bool isIn = await DataService.ContainsKey_Prefs(prefsKey);
                Debug.Log($"Test_ContainsKey_Prefs isIn: {isIn}");
            });
        }

        /// <summary>
        /// 测试删除Prefs
        /// </summary>
        public void Test_DeletData_Prefs()
        {
            UniTask.ToCoroutine(async () =>
            {
                bool isDele = await DataService.DeletData_Prefs(prefsKey);
                Debug.Log($"Test_DeletData_Prefs isIn: {isDele}");
            });
        }

        /// <summary>
        /// 测试清除Prefs
        /// </summary>
        public void Test_ClearSave_Prefs()
        {
            UniTask.ToCoroutine(async () =>
            {
                bool isIn = await DataService.ContainsKey_Prefs(prefsKey);
                Debug.Log($"Test_ClearSave_Prefs isIn: {isIn}");

                await DataService.ClearSave_Prefs();
                
                bool isInEnd = await DataService.ContainsKey_Prefs(prefsKey);
                Debug.Log($"Test_ClearSave_Prefs isInEnd: {isInEnd}");
            });
        }

        #endregion

        #region Memory

        /// <summary>
        /// 测试存储内存
        /// </summary>
        public void Test_Save_Memory()
        {
            UniTask.ToCoroutine(async () =>
            {
                await DataService.SaveOrUpdate_Memory(memoryKey, testClass, true);
                Debug.Log("Test_Save_Memory 存储数据成功");
            });
        }

        /// <summary>
        /// 测试加载内存
        /// </summary>
        public void Test_Load_Memory()
        {
            UniTask.ToCoroutine(async () =>
            {
                TestClass tc = await DataService.LoadData_Memory<TestClass>(memoryKey);
                if (tc != null)
                {
                    Debug.Log("Test_Load_Memory 读取数据成功");
                }
            });
        }

        public void Test_ContainsKey_Memory()
        {
            UniTask.ToCoroutine(async () =>
            {
                bool isIn = await DataService.ContainsKey_Memory(memoryKey);
                Debug.Log($"Test_ContainsKey_Memory isIn: {isIn}");
            });
        }

        /// <summary>
        /// 测试删除内存
        /// </summary>
        public void Test_DeletData_Memory()
        {
            UniTask.ToCoroutine(async () =>
            {
                bool isDele = await DataService.DeletData_Memory(memoryKey);
                Debug.Log($"Test_DeletData_Memory isIn: {isDele}");
            });
        }

        /// <summary>
        /// 测试清除内存
        /// </summary>
        public void Test_ClearSave_Memory()
        {
            UniTask.ToCoroutine(async () =>
            {
                bool isIn = await DataService.ContainsKey_Memory(memoryKey);
                Debug.Log($"Test_ClearSave_Memory isIn: {isIn}");

                await DataService.ClearSave_Memory();
                
                bool isInEnd = await DataService.ContainsKey_Memory(memoryKey);
                Debug.Log($"Test_ClearSave_Memory isInEnd: {isInEnd}");
            });
        }

        #endregion

        #region 无需参考，实现测试的无用代码

        /// <summary>
        /// 测试缓存网络图片
        /// </summary>
        private string textureCacheKey = "CachedTexture";
        public RawImage testNetImg = null;

        /// <summary>
        /// 测试缓存网络图片
        /// </summary>
        public void Test_CacheNetTexture_Memory()
        {
            UniTask.ToCoroutine(async () =>
            {
                const string url = "https://raw.githubusercontent.com/mattak/Unicache/master/art/cachepig.png";

                Texture2D txt2d = await DownloadTextureAsync(url);

                if (txt2d == null)
                {
                    Debug.Log($"DownloadTextureAsync 获取Texture2D失败");
                }
                
                await DataService.SaveOrUpdate_Memory(memoryKey, txt2d, true);
                Debug.Log("Test_CacheNetTexture_Memory 存储图片数据成功");
            });
        }

        /// <summary>
        /// 测试加载内存图片
        /// </summary>
        public void Test_LoadNetTexture_Memory()
        {
            UniTask.ToCoroutine(async () =>
            {
                Texture2D tc = await DataService.LoadData_Memory<Texture2D>(memoryKey);
                if (tc != null)
                {
                    Debug.Log("Test_Load_Memory 读取数据成功");
                }

                testNetImg.texture = tc;
            });
        }
        
        /// <summary>
        /// 异步下载图片方法
        /// </summary>
        protected async UniTask<Texture2D> DownloadTextureAsync(string url)
        {
            using var request = UnityWebRequestTexture.GetTexture(url);
            await request.SendWebRequest();

            if (request.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError($"下载失败：{request.error}");
                return null;
            }

            return DownloadHandlerTexture.GetContent(request);
        }

        #endregion
        
    }
}



